package com.nuo.laboratory.jdk;

import cn.hutool.core.date.*;
import cn.hutool.core.lang.Assert;
import lombok.Builder;
import lombok.Data;
import org.junit.Test;

import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @author LGC
 * @date 2022/4/28 11:25
 */
public class OptionalTest {


    @Test
    public void testAssert() {
        Assert.isTrue(true, "结果不存在异常");
    }

    @Test
    public void testRandom() {

        Random random = new Random();
        double v = random.nextGaussian();
        System.out.println(v);

//        IntStream intStream = random.ints(0, 100);
//        intStream.limit(10).forEach(System.out::println);


        String encode = Base64.getEncoder().encodeToString("admin".getBytes(StandardCharsets.UTF_8));
        System.out.println("加密后:" + encode);//YWRtaW4=

        String decoder = new String(Base64.getDecoder().decode("YWRtaW4="));
        System.out.println("解密后：" + decoder);

        Random random2 = new Random();
        System.out.println(random2.nextInt(9));//0-9的随机数


    }


    private Date calculateDistributionTimeByOrderCreateTime(Date orderCreateTime) {
        DateTime DISTRIBUTION_TIME_SPLIT_TIME = new DateTime();
        DISTRIBUTION_TIME_SPLIT_TIME.setField(DateField.HOUR_OF_DAY, 15);
        DISTRIBUTION_TIME_SPLIT_TIME.setField(DateField.MINUTE, 0);
        DISTRIBUTION_TIME_SPLIT_TIME.setField(DateField.SECOND, 0);
        DateTime orderCreateDateTime = new DateTime(orderCreateTime);
        DateTime tomorrow = DateUtil.offsetDay(orderCreateDateTime, 1);
        DateTime theDayAfterTomorrow = DateUtil.offsetDay(orderCreateDateTime, 2);
        return orderCreateDateTime.isAfter(DISTRIBUTION_TIME_SPLIT_TIME) ? wrapDistributionTime(theDayAfterTomorrow) : wrapDistributionTime(tomorrow);
    }

    private Date wrapDistributionTime(DateTime distributionTime) {
        Date currentDistributionDateTime = new DateTime(distributionTime);
        Date plusOneDay = DateUtil.offsetDay(currentDistributionDateTime, 1);
        boolean isSunday = (Week.SUNDAY == DateUtil.dayOfWeekEnum(currentDistributionDateTime));
        return isSunday ? plusOneDay : currentDistributionDateTime;
    }

    /**
     * 有一个关于下单发货的需求：如果今天下午 3 点前进行下单，那么发货时间是明天，如果今天下午 3 点后进行下单，
     * 那么发货时间是后天，如果被确定的时间是周日，那么在此时间上再加 1 天为发货时间
     */
    @Test
    public void getTime() {
        String date1 = DateUtil.format(calculateDistributionTimeByOrderCreateTime(new Date()), "yyyy-MM-dd");
        System.out.println(date1);
        String date2 = DateUtil.format(calculateDistributionTimeByOrderCreateTime(DateUtil.parse("2022-05-03 09:09:09", DatePattern.NORM_DATETIME_PATTERN)), "yyyy-MM-dd");
        System.out.println(date2);
        String date3 = DateUtil.format(calculateDistributionTimeByOrderCreateTime(DateUtil.parse("2022-05-01 09:09:09", DatePattern.NORM_DATETIME_PATTERN)), "yyyy-MM-dd");
        System.out.println(date3);
        String date4 = DateUtil.format(calculateDistributionTimeByOrderCreateTime(DateUtil.parse("2022-05-01 15:59:09", DatePattern.NORM_DATETIME_PATTERN)), "yyyy-MM-dd");
        System.out.println(date4);

    }


    @Test
    public void testOptional() {
        // 多层次调用
        //if (outer != null && outer.nested != null && outer.nested.inner != null) {
        //    System.out.println(outer.nested.inner.foo);
        //}
        Optional.of(new Outer())
                .map(Outer::getNested)
                .map(Nested::getInner)
                .map(Inner::getFoo)
                .orElseThrow(() -> new NullPointerException("参数不能为空"));
    }

    public static void main(String[] args) {
        Optional<OptionalTest.User> userOptional = Optional.of(OptionalTest.User.builder().name("zhansan").age(10).build());
        Optional<OptionalTest.User> userOptional2 = Optional.empty();

        User user = userOptional.orElseThrow(() -> new IllegalArgumentException("参数异常"));

        User user1 = userOptional2.orElse(User.builder().name("default").age(10).build());

        System.out.println(user);
        System.out.println(user1);

        int apply = Operator.ADD.apply(1, 2);
        int calculate = OptionalTest.calculate(1, 2, Operator.ADD);
        System.out.println("枚举适合类型固定" + apply + "calculate" + calculate);


        System.out.println("============");

        //创建Optional实例，也可以通过方法返回值得到。
        Optional<String> name = Optional.of("Sanaulla");

        //创建没有值的Optional实例，例如值为'null'
        Optional empty = Optional.ofNullable(null);

        //isPresent方法用来检查Optional实例是否有值。
        if (name.isPresent()) {
            //调用get()返回Optional值。
            System.out.println(name.get());
        }

        try {
            //在Optional实例上调用get()抛出NoSuchElementException。
            System.out.println(empty.get());
        } catch (NoSuchElementException ex) {
            System.out.println(ex.getMessage());
        }

        //ifPresent方法接受lambda表达式参数。
        //如果Optional值不为空，lambda表达式会处理并在其上执行操作。
        name.ifPresent((value) -> {
            System.out.println("The length of the value is: " + value.length());
        });

        //如果有值orElse方法会返回Optional实例，否则返回传入的错误信息。
        System.out.println(empty.orElse("There is no value present!"));
        System.out.println(name.orElse("There is some value!"));

        //orElseGet与orElse类似，区别在于传入的默认值。
        //orElseGet接受lambda表达式生成默认值。
        System.out.println(empty.orElseGet(() -> "Default Value"));
        System.out.println(name.orElseGet(() -> "Default Value"));

        try {
            //orElseThrow与orElse方法类似，区别在于返回值。
            //orElseThrow抛出由传入的lambda表达式/方法生成异常。
//            empty.orElseThrow(ValueAbsentException::new);
        } catch (Throwable ex) {
            System.out.println(ex.getMessage());
        }

        //map方法通过传入的lambda表达式修改Optonal实例默认值。
        //lambda表达式返回值会包装为Optional实例。
        Optional<String> upperName = name.map((value) -> value.toUpperCase());
        System.out.println(upperName.orElse("No value found"));

        //flatMap与map(Funtion)非常相似，区别在于lambda表达式的返回值。
        //map方法的lambda表达式返回值可以是任何类型，但是返回值会包装成Optional实例。
        //但是flatMap方法的lambda返回值总是Optional类型。
        upperName = name.flatMap((value) -> Optional.of(value.toUpperCase()));
        System.out.println(upperName.orElse("No value found"));

        //filter方法检查Optiona值是否满足给定条件。
        //如果满足返回Optional实例值，否则返回空Optional。
        Optional<String> longName = name.filter((value) -> value.length() > 6);
        System.out.println(longName.orElse("The name is less than 6 characters"));

        //另一个示例，Optional值不满足给定条件。
        Optional<String> anotherName = Optional.of("Sana");
        Optional<String> shortName = anotherName.filter((value) -> value.length() > 6);
        System.out.println(shortName.orElse("The name is less than 6 characters"));

    }

    @Data
    @Builder
    public static class User {
        private String name;
        private Integer age;
    }

    public static int calculate(int a, int b, Operator operator) {
        return operator.apply(a, b);
    }
}

class Outer {
    Nested nested;

    Nested getNested() {
        return nested;
    }
}

class Nested {
    Inner inner;

    Inner getInner() {
        return inner;
    }
}

class Inner {
    String foo;

    String getFoo() {
        return foo;
    }
}

enum Operator {
    /**
     * 添加方法
     */
    ADD {
        @Override
        public int apply(int a, int b) {
            return a + b;
        }
    };
    // other operators

    public abstract int apply(int a, int b);

}



